package k8s

import (
	"fmt"
	"github.com/xuri/excelize/v2"
	k8sclient "k8s_gui_client/k8s/client"
	utils "k8s_gui_client/utils"
	"os"
	"time"
)

//node list
func GetNodes() (map[string]interface{}, error) {

	return k8sclient.CurrentK8sApiClient.GetAPI(k8sclient.GET_NODES)

}

func NodeURL(name string) string {
	return "/api/v1/nodes/" + name
}

func GetNodeYaml(name string) (string, error) {
	return k8sclient.CurrentK8sApiClient.GetAPIAsYaml(NodeURL(name))
}

//node 监控指标
func GetNodeMetrics() (map[string]interface{}, error) {

	Metrics, err := k8sclient.CurrentK8sApiClient.GetAPI("/apis/metrics.k8s.io/v1beta1/nodes")
	if err != nil {
		return make(map[string]interface{}), err
	}

	items := Metrics["items"].([]interface{})

	if len(items) > 0 {
		result := make(map[string]interface{})
		for _, item := range items {
			itemMap := item.(map[string]interface{})
			metadata := itemMap["metadata"].(map[string]interface{})
			name := metadata["name"].(string)

			result[name] = itemMap
		}
		return result, nil
	}

	return make(map[string]interface{}), nil
}

type NodeStatic struct {
	RequestsCpu    float64
	RequestsMemory float64
	LimitsCpu      float64
	LimitsMemory   float64
}

func ExportNodeReports() error {

	nodes, err := k8sclient.CurrentK8sApiClient.GetAPI("/api/v1/nodes")
	if err != nil {
		return err
	}

	os.MkdirAll("d:/tmp", os.ModePerm)

	f := excelize.NewFile()
	f.SetSheetName("Sheet1", "nodes")

	f.SetCellStr("nodes", "A1", "name")
	f.SetCellStr("nodes", "B1", "cpu")
	f.SetCellStr("nodes", "C1", "memory(G)")
	f.SetCellStr("nodes", "D1", "usage.cpu")
	f.SetCellStr("nodes", "E1", "usage.memory(G)")

	f.SetCellStr("nodes", "F1", "requests.cpu")
	f.SetCellStr("nodes", "G1", "requests.cpu(%)")
	f.SetCellStr("nodes", "H1", "requests.memory(G)")
	f.SetCellStr("nodes", "I1", "requests.memory(%)")
	f.SetCellStr("nodes", "J1", "limits.cpu")
	f.SetCellStr("nodes", "K1", "limits.memory(G)")

	items := nodes["items"].([]interface{})

	Metrics, err := GetNodeMetrics()
	if err != nil {
		return err
	}

	pods, err := k8sclient.CurrentK8sApiClient.GetAPI("/api/v1/pods")
	if err != nil {
		return err
	}
	poditems := pods["items"].([]interface{})
	nodeStatics := make(map[string]*NodeStatic)
	for _, poditem := range poditems {
		pod := poditem.(map[string]interface{})
		spec := pod["spec"].(map[string]interface{})

		nodeName := spec["nodeName"].(string)
		if nodeStatics[nodeName] == nil {
			nodeStatics[nodeName] = &NodeStatic{
				RequestsCpu:    0.0,
				RequestsMemory: 0.0,
				LimitsCpu:      0.0,
				LimitsMemory:   0.0,
			}
		}

		if spec["containers"] != nil {
			requests_cpu := 0.0
			limits_cpu := 0.0
			requests_memory := 0.0
			limits_memory := 0.0
			containers := spec["containers"].([]interface{})

			if len(containers) > 0 {
				for _, _container := range containers {
					container := _container.(map[string]interface{})
					if container["resources"] != nil {
						resources := container["resources"].(map[string]interface{})

						if resources["requests"] != nil {
							requests := resources["requests"].(map[string]interface{})
							if requests["cpu"] != nil && requests["cpu"].(string) != "" {
								requests_cpu = requests_cpu + utils.To_cpu_h(requests["cpu"].(string))
							}
							if requests["memory"] != nil && requests["memory"].(string) != "" {
								requests_memory = requests_memory + utils.To_memory_g(requests["memory"].(string))
							}
						}
						if resources["limits"] != nil {
							limits := resources["limits"].(map[string]interface{})
							if limits["cpu"] != nil && limits["cpu"].(string) != "" {
								limits_cpu = limits_cpu + utils.To_cpu_h(limits["cpu"].(string))
							}
							if limits["memory"] != nil && limits["memory"].(string) != "" {
								limits_memory = limits_memory + utils.To_memory_g(limits["memory"].(string))
							}
						}
					}
				}

			}
			nodeStatics[nodeName].RequestsMemory = nodeStatics[nodeName].RequestsMemory+requests_memory
			nodeStatics[nodeName].RequestsCpu = nodeStatics[nodeName].RequestsCpu+requests_cpu
			nodeStatics[nodeName].LimitsMemory = nodeStatics[nodeName].LimitsMemory+limits_memory
			nodeStatics[nodeName].LimitsCpu = nodeStatics[nodeName].LimitsCpu+limits_cpu
		}
	}
	for index, item := range items {
		node := item.(map[string]interface{})
		metadata := node["metadata"].(map[string]interface{})

		status := node["status"].(map[string]interface{})

		name := metadata["name"].(string)

		f.SetCellStr("nodes", fmt.Sprintf("A%d", index+2), name)
		if status["allocatable"] != nil {
			allocatable := status["allocatable"].(map[string]interface{})
            cpu := utils.To_cpu_h((allocatable["cpu"].(string)))
			f.SetCellFloat("nodes", fmt.Sprintf("B%d", index+2),cpu , 2, 32)
			memory :=utils.To_memory_g((allocatable["memory"].(string)))
			f.SetCellFloat("nodes", fmt.Sprintf("C%d", index+2),memory , 2, 32)
		
			if Metrics[name] != nil {
				Metric := Metrics[name].(map[string]interface{})
				if Metric["usage"] != nil {
					usage := Metric["usage"].(map[string]interface{})
					f.SetCellFloat("nodes", fmt.Sprintf("D%d", index+2), utils.To_cpu_h((usage["cpu"].(string))), 2, 32)
					f.SetCellFloat("nodes", fmt.Sprintf("E%d", index+2), utils.To_memory_g((usage["memory"].(string))), 2, 32)
	
				}
			}
			if nodeStatics[name] != nil {
	
				f.SetCellFloat("nodes", fmt.Sprintf("F%d", index+2), nodeStatics[name].RequestsCpu, 2, 32)
				f.SetCellFloat("nodes", fmt.Sprintf("G%d", index+2), nodeStatics[name].RequestsCpu / cpu *100.00, 2, 32)
					f.SetCellFloat("nodes", fmt.Sprintf("H%d", index+2), nodeStatics[name].RequestsMemory, 2, 32)
					f.SetCellFloat("nodes", fmt.Sprintf("I%d", index+2), nodeStatics[name].RequestsMemory/ memory *100.00, 2, 32)
					
					f.SetCellFloat("nodes", fmt.Sprintf("J%d", index+2), nodeStatics[name].LimitsCpu, 2, 32)
					f.SetCellFloat("nodes", fmt.Sprintf("K%d", index+2), nodeStatics[name].LimitsMemory, 2, 32)
	
			}
		}

		
	}

	filename := fmt.Sprintf("d:/tmp/nodes-%s.xlsx", time.Now().Format("20060102150405000"))
	if err := f.SaveAs(filename); err != nil {
		return err
	}
	return utils.ExecRun(fmt.Sprintf("cmd.exe /k start %s ", filename))
}
